package com.zmj.sy.mom.srv.aps.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zmj.sy.mom.srv.aps.bean.entity.base.BaseEntity;
import com.zmj.sy.mom.srv.aps.bean.entity.mes.*;
import com.zmj.sy.mom.srv.aps.bean.entity.order.ApsWorkDetail;
import com.zmj.sy.mom.srv.aps.bean.entity.third.SinoCamReceiveNestExcess;
import com.zmj.sy.mom.srv.aps.bean.entity.third.SinoCamReceiveNestNest;
import com.zmj.sy.mom.srv.aps.bean.entity.third.SinoCamReceiveNestPart;
import com.zmj.sy.mom.srv.aps.bean.entity.third.SinoCamReceiveNestPlate;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseIdReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseIdsReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseListResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.pick.*;
import com.zmj.sy.mom.srv.aps.config.ProjectConfig;
import com.zmj.sy.mom.srv.aps.feign.PudaApiClient;
import com.zmj.sy.mom.srv.aps.feign.WmsApiClient;
import com.zmj.sy.mom.srv.aps.mapper.*;
import com.zmj.sy.mom.srv.aps.utils.SerialCodeUtils;
import com.zmj.sy.mom.srv.aps.utils.SyExceptionUtils;
import com.zmj.sy.mom.srv.aps.utils.WorkshopProp;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Service
public class PickService {

    private final PickMapper pickMapper;

    private final SerialCodeUtils serialCodeUtils;

    private final WmsPlatePickMapper wmsPlatePickMapper;

    private final PlateMapper plateMapper;

    private final WmsApiClient wmsApiClient;

    private final ProjectConfig projectConfig;
    private final PudaApiClient pudaApiClient;
    private final SinoCamReceiveNestNestMapper sinoCamReceiveNestNestMapper;
    private final SinoCamReceiveNestPlateMapper sinoCamReceiveNestPlateMapper;
    private final SinoCamReceiveNestPartMapper sinoCamReceiveNestPartMapper;
    private final PlatePhaseMapper platePhaseMapper;
    private final SinoCamReceiveNestExcessMapper sinoCamReceiveNestExcessMapper;
    private final ApsWorkDetailMapper apsWorkDetailMapper;
    private final WorkDetailTaskMapper workDetailTaskMapper;


    public BaseListResVo<PickPlateListResVo> plateList(PickPlateListReqVo reqVo) {

        List<Pick> list = pickMapper.lambdaQuery()
                .eq(Pick::getType, 1)
                .eq(reqVo.getSendStatus()!= null, Pick::getSendStatus, reqVo.getSendStatus())
                .like(StringUtils.hasText(reqVo.getPickCode()), Pick::getPickCode, reqVo.getPickCode())
                .orderByDesc(Pick::getCreateDateTime)
                .list();

        List<PickPlateListResVo> collect = list.stream().map(e -> {
            PickPlateListResVo vo = new PickPlateListResVo();
            BeanUtils.copyProperties(e, vo);
            return vo;
        }).collect(Collectors.toList());

        return new BaseListResVo<>(collect);
    }

    @Transactional
    public Integer plateAdd(PickPlateAddReqVo reqVo) {
        Pick pick = new Pick();
        String max = serialCodeUtils.pickPlate();
        pick.setPickCode(max);
        pick.setUsername(reqVo.getUsername());
        pick.setUserCode(reqVo.getUserCode());
        pick.setType(1);
        pick.setSendStatus(1);
        pickMapper.insert(pick);
        return pick.getId();
    }

    @Transactional
    public void plateDel(BaseIdReqVo reqVo) {
        Pick pick = pickMapper.selectById(reqVo.getId());
        if(pick == null){
            return ;
        }

        if(!pick.getType().equals(1)){
            throw SyExceptionUtils.e("只能删除钢板的领料单");
        }

        Integer count = wmsPlatePickMapper.lambdaQuery()
                .eq(WmsPlatePick::getPickId, pick.getId())
                .count();
        if(count > 0){
            throw SyExceptionUtils.e("领料单上有钢板，不允许删除");
        }

        pickMapper.deleteById(reqVo.getId());
    }

    @Transactional
    public void plateBind(PickPlateBindReqVo reqVo) {

        if(CollUtil.isEmpty(reqVo.getPlateId())){
            throw SyExceptionUtils.e("请选择钢板");
        }

        if(reqVo.getPickId() == null){
            throw SyExceptionUtils.e("领料单未选择");
        }

        Pick pick = pickMapper.selectById(reqVo.getPickId());

        if(pick.getSendStatus() > 1){
            throw SyExceptionUtils.e("已下发的领料单不允许再绑定钢板!");
        }

        WmsPlatePick one = wmsPlatePickMapper.lambdaQuery()
                .eq(WmsPlatePick::getPickId, pick.getId())
                .orderByDesc(WmsPlatePick::getPickListItem)
                .last(" limit 1 ").one();

        int seq = 0;
        if(one != null){
            seq = one.getPickListItem() ;
        }
        List<WmsPlatePick> list = wmsPlatePickMapper.lambdaQuery()
                .in(WmsPlatePick::getId, reqVo.getPlateId())
                .orderByDesc(WmsPlatePick::getStoragePlace, WmsPlatePick::getSeq)
                .list();
        long count = list.stream().filter(e -> e.getPickId() != null || StringUtils.hasText(e.getPickingListNo())).count();
        if(count > 0){
            throw SyExceptionUtils.e("该钢板已经绑定过领料单");
        }

        for (WmsPlatePick wmsPlatePick : list) {
            wmsPlatePick.setPickId(pick.getId());
            wmsPlatePick.setPickingListNo(pick.getPickCode());
            wmsPlatePick.setPickListItem(++seq);
            wmsPlatePickMapper.updateById(wmsPlatePick);
        }

    }

    @Transactional
    public void plateUnbind(PickPlateUnbindReqVo reqVo) {
        if(reqVo.getPlateId() == null){
            throw SyExceptionUtils.e("请选择钢板");
        }

        if(reqVo.getPickId() == null){
            throw SyExceptionUtils.e("领料单未选择");
        }

        Pick pick = pickMapper.selectById(reqVo.getPickId());
        if(!pick.getSendStatus().equals(1)){
            throw SyExceptionUtils.e("该状态不允许删除钢板!");
        }

        wmsPlatePickMapper.lambdaUpdate()
                .eq(WmsPlatePick::getId, reqVo.getPlateId())
                .set(WmsPlatePick::getPickId, null)
                .set(WmsPlatePick::getPickingListNo, null)
                .update();
    }

    public BaseListResVo<PickPlateBindListResVo> plateBindList(BaseIdReqVo reqVo) {

        List<WmsPlatePick> list = wmsPlatePickMapper.lambdaQuery()
                .eq(WmsPlatePick::getPickId, reqVo.getId())
                .orderByAsc(WmsPlatePick::getPickListItem)
                .list();

        if(CollUtil.isEmpty(list)){
            return new BaseListResVo<>(CollUtil.newArrayList());
        }

        List<Integer> pickIdList = list.stream().map(WmsPlatePick::getPickId).distinct().collect(Collectors.toList());
        List<Pick> pickList = pickMapper.selectBatchIds(pickIdList);
        Map<Integer, Pick> pickMap = pickList.stream().collect(Collectors.toMap(BaseEntity::getId, e -> e));

        List<Plate> list1 = plateMapper.lambdaQuery().in(Plate::getMaterCode, list.stream().map(WmsPlatePick::getMaterialId).collect(Collectors.toList())).list();
        Map<String, Plate> map = list1.stream().collect(Collectors.toMap(Plate::getMaterCode, Function.identity()));
        List<PlatePhase> platePhaseList = platePhaseMapper.lambdaQuery()
                .in(PlatePhase::getPlateCode, map.keySet())
                .in(PlatePhase::getPhaseCode, "JG", "HG")
                .list();
        Map<String, PlatePhase> platePhaseMap = platePhaseList.stream().collect(Collectors.toMap(PlatePhase::getPlateCode, Function.identity()));


        List<SinoCamReceiveNestPlate> nestPlateList = sinoCamReceiveNestPlateMapper.lambdaQuery()
                .in(SinoCamReceiveNestPlate::getStockListNo, platePhaseMap.keySet())
                .list();
        Map<String, SinoCamReceiveNestPlate> nestPlateMap = nestPlateList.stream().collect(Collectors.toMap(SinoCamReceiveNestPlate::getStockListNo, Function.identity()));

        List<SinoCamReceiveNestExcess> nestExcessList = sinoCamReceiveNestExcessMapper.lambdaQuery()
                .in(SinoCamReceiveNestExcess::getStockListNo, platePhaseMap.keySet())
                .list();
        Map<String, SinoCamReceiveNestExcess> nestExcessMap = nestExcessList.stream().collect(Collectors.toMap(SinoCamReceiveNestExcess::getStockListNo, Function.identity()));

        List<WorkDetailTask> workDetailTaskList = workDetailTaskMapper.lambdaQuery()
                .in(WorkDetailTask::getMaterCode, list.stream().map(WmsPlatePick::getMaterialId).collect(Collectors.toList()))
                .in(WorkDetailTask::getPhaseCode, "JG", "HG")
                .eq(WorkDetailTask::getType, 1)
                .list();
        Map<String, WorkDetailTask> taskMap = workDetailTaskList.stream().collect(Collectors.toMap(e -> e.getMaterCode(), Function.identity()));


        List<PickPlateBindListResVo> collect = list.stream()
                .map(e -> {

                    PlatePhase platePhase = platePhaseMap.get(e.getMaterialId());

                    SinoCamReceiveNestPlate sinoCamReceiveNestPlate = nestPlateMap.get(e.getMaterialId());

                    PickPlateBindListResVo r = new PickPlateBindListResVo();
                    r.setId(e.getId());
                    r.setLevel(e.getPickListItem());
                    r.setNestId(map.get(e.getMaterialId()).getNestId());
                    r.setWeight(map.get(e.getMaterialId()).getWeight());
                    r.setPlateCode(e.getMaterialId());
                    r.setGroupCode(platePhase.getGroupCode());
                    r.setSpec(sinoCamReceiveNestPlate.getTexture());
                    r.setWidth(e.getWidth());
                    r.setLength(e.getLength());
                    r.setThickness(new BigDecimal(e.getPlateThick()));
                    if(nestExcessMap.get(e.getMaterialId()) != null){
                        SinoCamReceiveNestExcess sinoCamReceiveNestExcess = nestExcessMap.get(e.getMaterialId());
                        r.setExcessCode(sinoCamReceiveNestExcess.getExMaterielId());
                    }

                    WorkDetailTask workDetailTask = taskMap.get(e.getMaterialId());
                    if(workDetailTask == null){
                        r.setSplitGroupCode(platePhase.getGroupCode());
                    } else {
                        r.setSplitGroupCode(workDetailTask.getStationCode());
                    }
                    r.setGroupCode(r.getSplitGroupCode());


                    r.setHeatNumber(sinoCamReceiveNestPlate.getHeatNumber());
                    r.setStatus(e.getPlateState());
                    r.setPositionCode(sinoCamReceiveNestPlate.getPositionCode());
                    r.setSequence(sinoCamReceiveNestPlate.getSequence());
                    Pick pick = pickMap.get(e.getPickId());
                    if (pick != null) {
                        r.setPickCode(pick.getPickCode());
                    }

                    String statusStr = "";
//                    if(StringUtils.hasText(r.getPickCode())){
//                        statusStr = r.getPickCode();
//                    }
                    if(r.getStatus() < 4 ){
                        r.setStatusStr(statusStr + "(0/1)");
                    } else {
                        r.setStatusStr(statusStr + "(1/1)");
                    }
                    if (!ObjectUtils.isEmpty(e.getPickDateTime())) {
                        r.setPickDateTime(LocalDateTime.parse(e.getPickDateTime().format(DatePattern.NORM_DATETIME_FORMATTER), DatePattern.NORM_DATETIME_FORMATTER));
                    }
                    if (!ObjectUtils.isEmpty(e.getOutTime())) {
                        r.setOutTime(LocalDateTime.parse(e.getOutTime().format(DatePattern.NORM_DATETIME_FORMATTER), DatePattern.NORM_DATETIME_FORMATTER));
                    }
                    r.setPickUserName(e.getPickUserName());

                    return r;
                })
                .collect(Collectors.toList());

        return new BaseListResVo<>(collect);
    }

    @Transactional
    public void plateSend(BaseIdReqVo reqVo) {

        Pick pick = pickMapper.selectById(reqVo.getId());
        if(pick == null){
            throw SyExceptionUtils.e("领料单不存在");
        }
        pick.setSendStatus(2);
        pick.setSendDateTime(LocalDateTime.now());
        pickMapper.updateById(pick);

        List<WmsPlatePick> list = wmsPlatePickMapper.lambdaQuery()
                .eq(WmsPlatePick::getPickId, pick.getId())
                .orderByAsc(WmsPlatePick::getPickListItem)
                .list();

        if(CollUtil.isEmpty(list)){
            throw SyExceptionUtils.e("该领料单没有钢板!");
        }

        for(WmsPlatePick e : list){
            e.setPlateState(2);
            wmsPlatePickMapper.updateById(e);

            ApsWorkDetail one = apsWorkDetailMapper.lambdaQuery()
                    .eq(ApsWorkDetail::getMaterNo, e.getMaterialId())
                    .eq(ApsWorkDetail::getPhaseCode, WorkshopProp.LL_PHASE_CODE)
                    .one();
            one.setStatus(3);
            one.setActualStartDateTime(LocalDateTime.now());
            apsWorkDetailMapper.updateById(one);
        }

        plateMapper.lambdaUpdate()
                .in(Plate::getId, list.stream().map(WmsPlatePick::getPlateId).collect(Collectors.toList()))
                .set(Plate::getStatus, 2)
                .update();

        wmsApiClient.sendLingliao(list);

//        普达分捡
        if (projectConfig.isPudaOpen()) {
            for (WmsPlatePick wmsPlatePick : list) {

                SinoCamReceiveNestPlate nestPlate = sinoCamReceiveNestPlateMapper.lambdaQuery().eq(SinoCamReceiveNestPlate::getStockListNo, wmsPlatePick.getMaterialId()).one();
                List<SinoCamReceiveNestPart> nestPartList = sinoCamReceiveNestPartMapper.lambdaQuery().eq(SinoCamReceiveNestPart::getPlateCode, nestPlate.getStockListNo()).list();
                SinoCamReceiveNestNest nestNest = sinoCamReceiveNestNestMapper.lambdaQuery().eq(SinoCamReceiveNestNest::getReceiveNestId, nestPlate.getReceiveNestId()).one();

                for (SinoCamReceiveNestPart part : nestPartList) {
                    pudaApiClient.sendNestResult(nestNest.getSplitGroupCode(),
                            wmsPlatePick.getMaterialId(), new BigDecimal(wmsPlatePick.getPlateThick()), nestNest.getNestDxfUrl(),
                            part.getNestId(), part.getQuantity().toString());
                }


            }
        }


    }

    @Transactional
    public void plateGroup(PickPlateGroupReqVo reqVo) {
        WmsPlatePick wmsPlatePickList = wmsPlatePickMapper.selectById(reqVo.getPlateIds());
        if(wmsPlatePickList == null){
            throw SyExceptionUtils.e("请选择钢板");
        }

        Plate plate = plateMapper.lambdaQuery().eq(Plate::getMaterCode, wmsPlatePickList.getMaterialId()).one();
        if(plate == null){
            throw SyExceptionUtils.e("钢板不存在");
        }

        Map<String, String> fjGroup = new HashMap<>();
        fjGroup.put("1-1_HYQG_00", "1-1_RGFJ_00");
        fjGroup.put("1-2_JGQG_00", "1-2_ZDFJ_00");
        fjGroup.put("1-3_JGQG_00", "1-3_ZDFJ_00");

        PlatePhase one = platePhaseMapper.lambdaQuery().eq(PlatePhase::getPlateCode, plate.getMaterCode()).in(PlatePhase::getPhaseCode, "JG", "HG").one();

        if(one == null){
            throw SyExceptionUtils.e("{} 没有找到切割工序", plate.getMaterCode());
        }
        one.setGroupCode(reqVo.getGroupCode());
        platePhaseMapper.updateById(one);


        PlatePhase nestPhase = platePhaseMapper.lambdaQuery().eq(PlatePhase::getPlateCode, plate.getMaterCode()).eq(PlatePhase::getPhaseSeq, one.getPhaseSeq() + 1).one();
        nestPhase.setGroupCode(fjGroup.get(one.getGroupCode()));
        platePhaseMapper.updateById(nestPhase);
    }

    public String replaceSplitGroup(String workChain, String chainGroupCode, String replaceGroupCode) {
        String[] groupSplit = chainGroupCode.split(",");
        String[] workChainSplit =  workChain.split("-");
        Integer index = null;
        for (int i = 0; i < workChainSplit.length; i++) {
            if(projectConfig.getCuttingProcess().contains(workChainSplit[i])){
                index = i;
                break;
            }
        }

        if(index == null){
            return null;
        }
        groupSplit[index] = replaceGroupCode;
        return String.join(",", groupSplit);
    }

    @Transactional
    public void plateMove(PickPlateUpReqVo reqVo) {
        WmsPlatePick source = wmsPlatePickMapper.selectById(reqVo.getId());
        Pick pick = pickMapper.selectById(source.getPickId());
        if(pick == null) {
            throw SyExceptionUtils.e("领料单不存在");
        }
        if(!pick.getSendStatus().equals(1)){
            throw SyExceptionUtils.e("已下发后不允许移动!");
        }

        WmsPlatePick target = null;
        if (reqVo.getType().equals(1)) {
            target = wmsPlatePickMapper.lambdaQuery()
                    .eq(WmsPlatePick::getPickId, source.getPickId())
                    .lt(WmsPlatePick::getPickListItem, source.getPickListItem())
                    .orderByDesc(WmsPlatePick::getPickListItem)
                    .last(" limit 1 ")
                    .one();
        } else {
            target = wmsPlatePickMapper.lambdaQuery()
                    .eq(WmsPlatePick::getPickId, source.getPickId())
                    .gt(WmsPlatePick::getPickListItem, source.getPickListItem())
                    .orderByAsc(WmsPlatePick::getPickListItem)
                    .last(" limit 1 ")
                    .one();
        }

        if(target == null){
            return ;
        }

        Integer upSeq = source.getPickListItem();
        source.setPickListItem(target.getPickListItem());
        target.setPickListItem(upSeq);

        wmsPlatePickMapper.updateById(source);
        wmsPlatePickMapper.updateById(target);
    }

    public PickCutTimeResVo cutTime(BaseIdsReqVo reqVo) {
        if(CollUtil.isEmpty(reqVo.getIds())){
            return new PickCutTimeResVo(0);
        }

        QueryWrapper<Object> query = Wrappers.query();
        query.in("pp.id", reqVo.getIds());
        query.isNotNull("move.total_cut_time");
        Integer sum = wmsPlatePickMapper.cutTime(query);

        if(sum == null){
            sum = 0;
        }

        return new PickCutTimeResVo(sum);
    }

    public void plateSendPd(String  pickingListNo,String plateCode) {
            List<WmsPlatePick> list = wmsPlatePickMapper.lambdaQuery()
                    .eq(StringUtils.hasText(pickingListNo),WmsPlatePick::getPickingListNo,pickingListNo)
                    .eq(StringUtils.hasText(plateCode),WmsPlatePick::getMaterialCode,plateCode)
                    .orderByAsc(WmsPlatePick::getPickListItem)
                    .list();
            for (WmsPlatePick wmsPlatePick : list){
                plateCode=wmsPlatePick.getMaterialCode();
                SinoCamReceiveNestPlate nestPlate = sinoCamReceiveNestPlateMapper.lambdaQuery().eq(SinoCamReceiveNestPlate::getStockListNo,plateCode).one();
                List<SinoCamReceiveNestPart> nestPartList = sinoCamReceiveNestPartMapper.lambdaQuery().eq(SinoCamReceiveNestPart::getPlateCode, plateCode).list();
                SinoCamReceiveNestNest nestNest = sinoCamReceiveNestNestMapper.lambdaQuery().eq(SinoCamReceiveNestNest::getReceiveNestId, nestPlate.getReceiveNestId()).one();

                for (SinoCamReceiveNestPart part : nestPartList) {
                    pudaApiClient.sendNestResult(nestNest.getSplitGroupCode(),
                            plateCode, new BigDecimal(wmsPlatePick.getPlateThick()), nestNest.getNestDxfUrl(),
                            part.getNestId(), part.getQuantity().toString());
                }
            }








    }
}
